package com.zuo.mall.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zuo.mall.bo.AdminUserDetails;
import com.zuo.mall.common.util.RequestUtil;
import com.zuo.mall.entity.UmsAdmin;
import com.zuo.mall.entity.UmsAdminLoginLog;
import com.zuo.mall.entity.UmsResource;
import com.zuo.mall.entity.UmsRole;
import com.zuo.mall.mapper.UmsAdminLoginLogMapper;
import com.zuo.mall.mapper.UmsAdminMapper;
import com.zuo.mall.mapper.UmsAdminRoleRelationMapper;
import com.zuo.mall.security.util.JwtTokenUtil;
import com.zuo.mall.security.util.SpringUtil;
import com.zuo.mall.service.UmsAdminCacheService;
import com.zuo.mall.service.UmsAdminService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.jsonwebtoken.lang.Collections;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 后台用户表 服务实现类
 * </p>
 *
 * @author zuo
 * @since 2023-10-21
 */
@Service
public class UmsAdminServiceImpl extends ServiceImpl<UmsAdminMapper, UmsAdmin> implements UmsAdminService {


    @Autowired
    private UmsAdminLoginLogMapper adminLoginLogMapper;

    @Autowired
    private UmsAdminRoleRelationMapper adminRoleRelationMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Override
    public UserDetails loadUserByUsername(String username) {
        UmsAdmin admin = getAdminByUsername(username);
        if (admin != null) {
            List<UmsResource> resourceList = getResourceList(admin.getId());
            return new AdminUserDetails(admin, resourceList);
        }
        throw new UsernameNotFoundException("用户名或者密码错误");
    }

    @Override
    public UmsAdmin getItem(Long adminId) {
        return baseMapper.selectById(adminId);
    }

    @Override
    public String login(String username, String password) {
        String token = null;
        // 密码需要客户端加密后传递
        UserDetails userDetails = loadUserByUsername(username);
        userDetails.getPassword();
        if (!passwordEncoder.matches(password, userDetails.getPassword())) {
            return "密码错误";
        }
        // 检查账号是否禁用
        if (userDetails.isEnabled()) {
            return "账号已被禁用";
        }

        // 将用户信息存入UsernamePasswordAuthenticationToken
        new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
        // 通过JWTTOKENUTIL 生成token
        token= jwtTokenUtil.generateToken(userDetails);
        // 记录登录日志
        insertLoginLog(username);
        // 返回token
        return token;
    }

    @Override
    public List<UmsRole> getRoleList(Long adminId) {
        return adminRoleRelationMapper.getRoleList(adminId);
    }

    /**
     * 插入用户登录日志
     * @param username
     */
    private void insertLoginLog(String username) {
        UmsAdmin admin = getAdminByUsername(username);
        if (admin == null) return;
        UmsAdminLoginLog adminLoginLog = new UmsAdminLoginLog();
        adminLoginLog.setAdminId(admin.getId());
        adminLoginLog.setCreateTime(LocalDateTime.now());
        // 获取登录地址的ip
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String requestIp = RequestUtil.getRequestIp(request);
        adminLoginLog.setIp(requestIp);
        adminLoginLogMapper.insert(adminLoginLog);
    }

    @Override
    public List<UmsResource> getResourceList(Long adminId) {
        // 先从缓存中获取
        UmsAdminCacheService cacheService = getCacheService();
        List<UmsResource> umsResourceList = cacheService.getReourceList(adminId);
        if (!Collections.isEmpty(umsResourceList)) {
            // 不是空缓存 直接返回
            return umsResourceList;
        }
        // 空缓存查询数据库
        umsResourceList = adminRoleRelationMapper.selectResourceListByAdminId(adminId);
        if (CollUtil.isNotEmpty(umsResourceList)) {
            // 缓存数据
            getCacheService().setResourceList(adminId, umsResourceList);
        }
        return umsResourceList;

    }

    @Override
    public UmsAdmin getAdminByUsername(String username) {
        // 首先从缓存获取username
        UmsAdmin admin = getCacheService().getAdmin(username);
        if (admin != null) {
            return admin;
        }
        // 缓存为空查询数据库
        LambdaQueryWrapper<UmsAdmin> queryWrapper = new LambdaQueryWrapper<>();

        admin = baseMapper.selectOne(queryWrapper.eq(UmsAdmin::getUsername, username));
        if (admin != null) {
            // 查询到先缓存
            getCacheService().setAdmin(admin);
            return admin;
        }
        return null;
    }

    private UmsAdminCacheService getCacheService() {
        return SpringUtil.getBean(UmsAdminCacheService.class);
    }

}

